﻿#pragma once

#include "yzrutil.h"

namespace yzrilyzr_util{
	template<typename V, u_index PoolSize>
	EBCLASS(Pool2){
	public:
	EBCLASS(PoolObject){
	public:
	V * object=nullptr;
	bool use=false;
	u_index index=-1;
	};

	private:
	PoolObject * pool[PoolSize];
	u_index freeIndexs[PoolSize];
	std::atomic<u_index> freeSize={0};
	std::atomic<u_index> _size={0};
	public:
	explicit Pool2(){
		for(u_index i=0; i < PoolSize; i++){
			pool[i]=new PoolObject();
			freeIndexs[i]=0;
			pool[i]->index=i;
		}
	}

	~Pool2(){
		for(u_index i=0; i < PoolSize; i++){
			delete pool[i]->object;
			delete pool[i];
		}
	}

	//最大容量
	u_index capacity() const{
		return PoolSize;
	}

	//使用量
	u_index size() const{
		return _size;
	}

	//获取使用量是否为空
	bool isEmpty() const{
		return _size == 0;
	}

	//循环获取对象
	PoolObject & get(u_index index) const{
		return *pool[index];
	}

	//借出并初始化
	V * borrowObject(){
		PoolObject & po=*pool[_size];
		V * v=po.object;
		if(v == nullptr){
			v=newInstance();
			po.object=v;
		} else onReuse(v);
		_size++;
		return v;
	}

	protected:
	virtual V * newInstance()=0;

	virtual void onReuse(V * v)=0;

	public:
		//归还对象
	void returnObjectLater(PoolObject & po){
		freeIndexs[freeSize]=po->index;
		freeSize++;
	}

	//归还对象
	void returnObjectLater(){
		for(u_index i=0, j=freeSize; i < j; i++){
			u_index lastIndex=_size - 1;
			_size--;
			u_index freeIndex=freeIndexs[i];
			if(freeIndex == lastIndex) return;
			PoolObject * toFree=pool[freeIndex];
			PoolObject * obLast=pool[lastIndex];
			pool[freeIndex]=obLast;
			pool[lastIndex]=toFree;
			obLast->index=freeIndex;
			toFree->index=lastIndex;
		}
		freeSize=0;
	}

	//归还对象
	void returnObject(PoolObject & toFree){
		u_index lastIndex=_size - 1;
		_size--;
		u_index freeIndex=toFree.index;
		if(freeIndex == lastIndex) return;
		PoolObject * obLast=pool[lastIndex];
		pool[freeIndex]=obLast;
		pool[lastIndex]=&toFree;
		obLast->index=freeIndex;
		toFree.index=lastIndex;
	}

	//归还对象
	void returnAllObject(){
		_size=0;
		freeSize=0;
	}

	//释放对象
	void clear(){
		for(u_index i=0; i < PoolSize; i++){
			delete pool[i]->object;
			pool[i]->object=nullptr;
		}
		_size=0;
		freeSize=0;
	}
	};
}